package com.tanhua.server.server;

import cn.hutool.core.collection.CollUtil;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.dubbo.api.MovementApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.VisitorsApi;
import com.tanhua.model.domian.UserInfo;
import com.tanhua.model.enums.CommentType;
import com.tanhua.model.mongo.Comment;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.MovementsVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.VisitorsVo;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.utils.Constants;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class MovementsService {

    @Autowired
    private OssTemplate ossTemplate;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @DubboReference
    private MovementApi movementApi;
    @DubboReference
    private UserInfoApi userInfoApi;
    @DubboReference
    private VisitorsApi visitorsApi;

    @Autowired
    private MqMessageService mqMessageService;
    /**
     * 发布动态
     *
     * @param movement
     * @param imageContent
     * @throws IOException
     */
    public void movements(Movement movement, MultipartFile[] imageContent) throws IOException {
        //检测动态内容是否为空
        if (StringUtils.isEmpty(movement.getTextContent())) {
            throw new BusinessException(ErrorResult.contentError());
        }
        //获取当前用户ID，将文件内容上传到OSS
        Long userId = UserHolder.getUserId();
        //用一个list来接受oss传来的路径
        List<String> url = new ArrayList<>();
        for (MultipartFile multipartFile : imageContent) {
            String upload = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            url.add(upload);
        }
        //将获取的数据封装到movement
        movement.setUserId(userId);
        movement.setMedias(url);
        //调用Api完成发布动态
        String publish = movementApi.publish(movement);
        mqMessageService.sendAudiMessage(publish);

    }

    /**
     * 查询我的动态
     *
     * @param userId
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult findByuserId(Long userId, Integer page, Integer pagesize) {
        //从movement取出所有动态
        PageResult pr = movementApi.findByUserId(userId, page, pagesize);

        List<Movement> items = (List<Movement>) pr.getItems();
        //判断是否为空
        if (items == null) {
            return pr;
        }
        //取出用户详细信息
        UserInfo userInfo = userInfoApi.findById(userId);
        //构建集合VO 返回多条动态数据
        ArrayList<MovementsVo> list = new ArrayList<>();
        //循环数据列表
        for (Movement item : items) {
            MovementsVo movementsVo = MovementsVo.init(userInfo, item);
            list.add(movementsVo);
        }
        pr.setItems(list);
        return pr;
    }

    /**
     * 好友动态
     *
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult friend(Integer page, Integer pagesize) {
        //获取本账户ID
        Long userId = UserHolder.getUserId();
        //获取好友动态
        List<Movement> list = movementApi.findFriendMovements(page, pagesize, userId);
        return getPageResult(page, pagesize, list);
       /* //判断是否为空
        if(list == null){
            return new PageResult();
        }
        //提取动态发布人ID列表
        List<Long> userIds = CollUtil.getFieldValues(list, "userId", Long.class);
        //根据动态发布人ID获得用户详情
        Map<Long, UserInfo> mapId = userInfoApi.findByIds(userIds, null);
        //构造一个Movement的VO对象
        List<MovementsVo> vos = new ArrayList<>();
        for (Movement movement : list) {
            UserInfo userInfo = mapId.get(movement.getUserId());
            if (userInfo != null) {
                MovementsVo init = MovementsVo.init(userInfo, movement);
                vos.add(init);
            }
        }
        //返回
        return new PageResult(page,pagesize,01,vos);*/
    }

    /**
     * 获得动态的共性方法
     *
     * @param page
     * @param pagesize
     * @param list
     * @return
     */
    public PageResult getPageResult(Integer page, Integer pagesize, List<Movement> list) {
        //判断是否为空
        if (CollUtil.isEmpty(list)) {
            return new PageResult();
        }
        //提取动态发布人ID列表
        List<Long> userIds = CollUtil.getFieldValues(list, "userId", Long.class);
        //根据动态发布人ID获得用户详情
        Map<Long, UserInfo> mapId = userInfoApi.findByIds(userIds, null);
        //构造一个Movement的VO对象
        List<MovementsVo> vos = new ArrayList<>();
        for (Movement movement : list) {
            UserInfo userInfo = mapId.get(movement.getUserId());
            if (userInfo != null) {
                MovementsVo vo = MovementsVo.init(userInfo, movement);
                String key = Constants.MOVEMENTS_INTERACT_KEY + movement.getId().toHexString();
                String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
                String hashkey1 = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();

                if (redisTemplate.opsForHash().hasKey(key, hashKey)) {
                    vo.setHasLiked(1);
                }
                if (redisTemplate.opsForHash().hasKey(key, hashkey1)) {
                    vo.setHasLoved(1);
                }

                vos.add(vo);
            }
        }
        //返回
        return new PageResult(page, pagesize, 01, vos);
    }

    public PageResult recommend(Integer page, Integer pageSize) {
        //从redis里面获取pid
        String redisKey = Constants.MOVEMENTS_RECOMMEND + UserHolder.getUserId();
        String redisValue = redisTemplate.opsForValue().get(redisKey);
        //判断推荐数据是否存在
        List<Movement> list = Collections.EMPTY_LIST;
        if (StringUtils.isEmpty(redisValue)) {
            //如果没有，就随机添入十条
            list = movementApi.randomMovements(pageSize);
        } else {
            //如果存在，处理pid数据   "16,17,18,19,20,21,10015,10020,10040,10064,10092,10093,10099,10067" 15
            String[] split = redisValue.split(",");
            //判断当前页的起始条数是否小于数组总数
            if ((page - 1) * pageSize < split.length) {
                List<Long> collect = Arrays.stream(split).skip((page - 1) * pageSize).limit(pageSize)
                        .map(e -> Long.valueOf(e))
                        .collect(Collectors.toList());
                //调用API根据PID数组查询动态数据
                list = movementApi.findMovementsByPids(collect);
            }
        }
        //调用公共方法构造返回值
        return getPageResult(page, pageSize, list);
    }

    public MovementsVo findById(String id) {
        //更具动态ID找到 动态
        Movement movement = movementApi.findById(id);
        //动态不为null时，根据动态里面的userId找到 用户 封装给Vo
        if (movement != null) {
            UserInfo userInfo = userInfoApi.findById(movement.getUserId());
            MovementsVo vo = MovementsVo.init(userInfo, movement);
            return vo;
        }
        return null;
    }

    /**
     * 喜欢
     * @param movementId
     * @return
     */
    public Integer love(String movementId) {
          //获取本账户ID
        Long userId = UserHolder.getUserId();
        //查询是否已经点了喜欢
       boolean bl =  movementApi.love(movementId,userId, CommentType.LOVE);
       //判断是否已经点了喜欢，如果点了 则报错返回
        if (bl) {
            throw new BusinessException(ErrorResult.loveError());
        }
        //创建一个comment对象，存入comment表
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LOVE.getType());
        comment.setUserId(userId);
        comment.setCreated(System.currentTimeMillis());
        //往movement更新数据
        Integer all = movementApi.updateLove(comment);
        //往redis存入hashkey
        String key = Constants.MOVEMENTS_INTERACT_KEY+movementId;
        String hashkey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(key, hashkey,"1");
        return all;
    }


    public Integer unlove(String movementId) {
        //获得本账户ID
        Long userId = UserHolder.getUserId();
        //查询数据库是否已经有了喜欢
        boolean b = movementApi.love(movementId, userId, CommentType.LOVE);
        //如果没有喜欢，则不能取消喜欢，报错
        if (!b){
            throw new BusinessException(ErrorResult.disloveError());
        }
        //封装comment数据，去comment集合中删除喜欢表，去movement表中更新数据
        Comment comment = new Comment();
        comment.setUserId(userId);
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LOVE.getType());

        Integer all = movementApi.deleteLove(comment);

        //删除redis里面的hashkey
        String key = Constants.MOVEMENTS_INTERACT_KEY+movementId;
        String hashkey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().delete(key,hashkey);

        return all;
    }

    public List<VisitorsVo> queryVisitorsList() {
        //查询访问时间
        String key = Constants.VISITORS_USER;
        String hashKey =String.valueOf(UserHolder.getUserId());
        String value = (String) redisTemplate.opsForHash().get(key, hashKey);
        Long data = StringUtils.isEmpty(value) ? null:Long.valueOf(value);
        //去visitors表查询看过我账户的ID
       List<Visitors> visitorsList = visitorsApi.queryVisitorsList(data,UserHolder.getUserId());
        if(CollUtil.isEmpty(visitorsList)) {
            return new ArrayList<>();
        }
        //根据ID找到用户详细userinfo
        List<Long> visitorUserIds = CollUtil.getFieldValues(visitorsList, "visitorUserId", Long.class);
        Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(visitorUserIds, null);
        //将visitors，userinfo封装到VisitorsVo返回
        ArrayList<VisitorsVo> Vos = new ArrayList<>();
        for (Visitors visitors : visitorsList) {
            UserInfo userInfo = userInfoMap.get(visitors.getVisitorUserId());
            if (userInfo != null) {
                VisitorsVo init = VisitorsVo.init(userInfo, visitors);
                Vos.add(init);
            }
        }
        return Vos;
    }
}
